#!/usr/bin/python
#
#   jab2web version 0.1
#
#       Sean Colyer
#       Tommy Murphy
#
#   Licensed Under the GPLv3
#
#   Usage: ./jab2web.py <config_file>
#

import sys          # system
import os           # filesystem stuff
import xmpp         # xmpppy library
import re           # regular expressions
import urllib       # url encoding
import urllib2      # make http requests

from time import sleep

# import pdb          # debugging

## config class ##
class j2wConfig:
    """Parse the config file and process messages."""

    def __init__(self, path):
        self.jidparams = {}
        self.rules = {}
            
        if os.access(path, os.R_OK):                    # read config file
            
            ruleLine = "^(\^.*\$)\s*(http.*)$"          # regex of a rule
            p = re.compile(ruleLine)
            
            for ln in open(path).readlines():
                if not ln.strip()[0] in ('#',';'):      # check if it's a comment
                    m = p.match(ln)                     # check if it's a rule       
                    if m != None:
                        key, val = m.groups()           # it is a rule, add it to rules!
                        key = re.compile(key)
                        self.rules[key] = val
                    else:
                        # if this doesnt work throw an exception
                        key,val = ln.strip().split('=',1)
                        self.jidparams[key] = val   
        else:
            print 'Invalid config file or improper permissions.'
            # throw exception
            sys.exit()


    def process(self, line, sender):
        """Match a message and determine response"""
        for key in self.rules.keys():                   # iterate over keys
            m = key.match(line)                         # check if input matches a key
            if m != None:
                url = self.rules[key]
                
                for grp in range(0, len(m.groups())):   # replaces ${number} placeholders
                    old = "$" + str(grp+1)
                    new = urllib.quote_plus(str(m.groups()[grp]))
                    url = url.replace(old, new)
                    
                old = "$name"                           # replace $name with the screename
                new = urllib.quote_plus(sender)
                url = url.replace(old,new)
                
                response = urllib2.urlopen(url)         # make the http request
                return response.read()
        # throw error message
        return "Command not found!"

## bot class ##
class j2wBot:
    """ The jab2web bot.  Uses regular expressions to match incoming
    message patters to URL's then replies with the output of the url """

    def __init__(self, config):
        self.config = config
        self.conn = None
        self._finished = False

    def connect(self):
        """Setup server connection"""

        if not self.conn:
            conn = xmpp.Client(self.config.jidparams['serviceName'], debug = [] )
            # conn = xmpp.Client(self.config.jidparams['serviceName']) # debugging on
            server = (self.config.jidparams['host'], int(self.config.jidparams['port']))
            if not conn.connect(server):
                self.log('Unable to contact server.')
                return None

            if not conn.auth(self.config.jidparams['user'], self.config.jidparams['pw']):
                self.log('Authorization failed.')
                return None

            conn.RegisterHandler('message', self.cb_message)
            conn.RegisterHandler('presence', self.cb_presence)
            conn.sendInitPresence()
            self.conn = conn

        return self.conn

    def listen(self):
        """Connect to server and handle messages. """

        if self.connect():
            self.log('Connected to server. Handling messages.')
        else:
            self.log('Could not connect to server.')
            return

        try:
            while not self._finished:
                if self.conn and self.conn.isConnected():
                    self.conn.Process(1)
                else:
                    self.conn = None
                    self.connect()
                    time.sleep(5)
        except KeyboardInterrupt:
            self.log('User requested abort')

        self.disconnect()

    def disconnect(self):
        """Disconnect and shutdown."""

        self.log('Disconnecting...')
        self.conn.disconnect

    def cb_message(self, conn, message):
        """Messages sent to the bot will arrive here. Command handling
        + routing is done in this function."""

        msg = message.getBody()
        sender = message.getFrom()
        if msg != None:
            self.log('Message:\t' + str(msg) + '\nUser:\t' + str(sender))
            reply = self.config.process(msg, str(sender))
            self.conn.send(xmpp.Message(sender, reply))

    def cb_presence(self, conn, presence):
        """Presence changes of clients will arrive here. Automatic
        authorizing and unauthorizing here."""

        presence_type = presence.getType()
        roster = self.conn.getRoster()
        try:
            roster.Authorize(presence.getFrom())
            self.log(str(presence.getFrom()) + ' Authorized for chat')
        except:
            pass
            self.log(str(presence.getFrom()) + ' Failed Authorization for chat')
        

    def log(self, text):
        """Log messages"""

        print text

## main program ##

if len(sys.argv) != 2:
    print "jab2web version 0.1"
    print "Usage: ./jab2web.py <config_file>"
    sys.exit(0)

myConfig = j2wConfig(sys.argv[1])
bot = j2wBot(myConfig)
bot.listen()
